From 0c4708b64fb4dbb260cd99e1269beac019f7eb83 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 23 Sep 2005 13:30:54 +0100 Subject: [PATCH] Add VGA acceleration support for cirrus logic device model Signed-off-by: Xiaofeng Ling Signed-off-by: Yunhong Jiang Signed-off-by: Asit Mallick --- tools/ioemu/hw/cirrus_vga.c | 24 ++- tools/ioemu/hw/pc.c | 7 +- tools/ioemu/hw/vga.c | 5 +- tools/ioemu/target-i386-dm/helper2.c | 2 + tools/ioemu/vl.c | 247 ++++++++++++++++++++++++++- tools/libxc/xc_vmx_build.c | 23 ++- 6 files changed, 284 insertions(+), 24 deletions(-) diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 7c34c57899..bcf9a56417 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -231,6 +231,8 @@ typedef struct CirrusVGAState { int cirrus_linear_io_addr; int cirrus_linear_bitblt_io_addr; int cirrus_mmio_io_addr; + unsigned long cirrus_lfb_addr; + unsigned long cirrus_lfb_end; uint32_t cirrus_addr_mask; uint32_t linear_mmio_mask; uint8_t cirrus_shadow_gr0; @@ -2447,6 +2449,10 @@ static void cirrus_update_memory_access(CirrusVGAState *s) { unsigned mode; + extern void unset_vram_mapping(unsigned long addr, unsigned long end); + extern void set_vram_mapping(unsigned long addr, unsigned long end); + extern int vga_accelerate; + if ((s->sr[0x17] & 0x44) == 0x44) { goto generic_io; } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { @@ -2454,17 +2460,21 @@ static void cirrus_update_memory_access(CirrusVGAState *s) } else { if ((s->gr[0x0B] & 0x14) == 0x14) { goto generic_io; - } else if (s->gr[0x0B] & 0x02) { - goto generic_io; - } - - mode = s->gr[0x05] & 0x7; - if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + } else if (s->gr[0x0B] & 0x02) { + goto generic_io; + } + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) + set_vram_mapping(s->cirrus_lfb_addr, s->cirrus_lfb_end); s->cirrus_linear_write[0] = cirrus_linear_mem_writeb; s->cirrus_linear_write[1] = cirrus_linear_mem_writew; s->cirrus_linear_write[2] = cirrus_linear_mem_writel; } else { generic_io: + if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) + unset_vram_mapping(s->cirrus_lfb_addr, s->cirrus_lfb_end); s->cirrus_linear_write[0] = cirrus_linear_writeb; s->cirrus_linear_write[1] = cirrus_linear_writew; s->cirrus_linear_write[2] = cirrus_linear_writel; @@ -3058,6 +3068,8 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, /* XXX: add byte swapping apertures */ cpu_register_physical_memory(addr, s->vram_size, s->cirrus_linear_io_addr); + s->cirrus_lfb_addr = addr; + s->cirrus_lfb_end = addr + VGA_RAM_SIZE; cpu_register_physical_memory(addr + 0x1000000, 0x400000, s->cirrus_linear_bitblt_io_addr); } diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 33df03bc5d..92464250eb 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -385,6 +385,7 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, unsigned long bios_offset, vga_bios_offset; int bios_size, isa_bios_size; PCIBus *pci_bus; + extern void * shared_vram; linux_boot = (kernel_filename != NULL); @@ -511,14 +512,14 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, if (cirrus_vga_enabled) { if (pci_enabled) { pci_cirrus_vga_init(pci_bus, - ds, phys_ram_base + ram_size, ram_size, + ds, shared_vram, ram_size, vga_ram_size); } else { - isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size, + isa_cirrus_vga_init(ds, shared_vram, ram_size, vga_ram_size); } } else { - vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, + vga_initialize(pci_bus, ds, shared_vram, ram_size, vga_ram_size); } diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index 144ae741c6..a5084e0e67 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1568,6 +1568,8 @@ void vga_update_display(void) s->graphic_mode = graphic_mode; full_update = 1; } + + full_update = 1; switch(graphic_mode) { case GMODE_TEXT: vga_draw_text(s, full_update); @@ -1848,6 +1850,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, unsigned long vga_ram_offset, int vga_ram_size) { int i, j, v, b; + extern void* shared_vram; for(i = 0;i < 256; i++) { v = 0; @@ -1876,7 +1879,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort * when guest write vga mem, so allocate a new one */ - s->vram_ptr = qemu_mallocz(vga_ram_size); + s->vram_ptr = shared_vram; s->vram_offset = vga_ram_offset; s->vram_size = vga_ram_size; diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index 4ee1410b20..49c2804c72 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -54,6 +54,8 @@ #include "exec-all.h" #include "vl.h" +void *shared_vram; + shared_iopage_t *shared_page = NULL; extern int reset_requested; diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 426205bc27..2fd60a5aba 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -134,6 +134,7 @@ int pci_enabled = 1; int prep_enabled = 0; int rtc_utc = 1; int cirrus_vga_enabled = 1; +int vga_accelerate = 1; int graphic_width = 800; int graphic_height = 600; int graphic_depth = 15; @@ -141,6 +142,12 @@ int full_screen = 0; TextConsole *vga_console; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; int xc_handle; +unsigned long *vgapage_array; +unsigned long *freepage_array; +unsigned long free_pages; +void *vtop_table; +unsigned long toptab; +unsigned long vgaram_pages; /***********************************************************/ /* x86 ISA bus support */ @@ -2162,6 +2169,7 @@ void help(void) "-isa simulate an ISA-only system (default is PCI system)\n" "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n" " (default is CL-GD5446 PCI VGA)\n" + "-vgaacc [0|1] 1 to accelerate CL-GD5446 speed, default is 1\n" #endif "-loadvm file start right away with a saved state (loadvm in monitor)\n" "\n" @@ -2251,6 +2259,7 @@ enum { QEMU_OPTION_serial, QEMU_OPTION_loadvm, QEMU_OPTION_full_screen, + QEMU_OPTION_vgaacc, }; typedef struct QEMUOption { @@ -2327,6 +2336,7 @@ const QEMUOption qemu_options[] = { { "pci", 0, QEMU_OPTION_pci }, { "nic-pcnet", 0, QEMU_OPTION_nic_pcnet }, { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, + { "vgaacc", HAS_ARG, QEMU_OPTION_vgaacc }, { NULL }, }; @@ -2343,6 +2353,177 @@ static uint8_t *signal_stack; #define NET_IF_USER 1 #define NET_IF_DUMMY 2 +#include + +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER) +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) + +#ifdef __i386__ +#define _LEVEL_3_ 0 +#else +#define _LEVEL_3_ 1 +#endif + +#if _LEVEL_3_ +#define L3_PROT (_PAGE_PRESENT) +#define L1_PAGETABLE_ENTRIES 512 +#else +#define L1_PAGETABLE_ENTRIES 1024 +#endif + +inline int +get_vl2_table(unsigned long count, unsigned long start) +{ +#if _LEVEL_3_ + return ((start + (count << PAGE_SHIFT)) >> L3_PAGETABLE_SHIFT) & 0x3; +#else + return 0; +#endif +} + +int +setup_mapping(int xc_handle, u32 dom, unsigned long toptab, unsigned long *mem_page_array, unsigned long *page_table_array, unsigned long v_start, unsigned long v_end) +{ + l1_pgentry_t *vl1tab=NULL, *vl1e=NULL; + l2_pgentry_t *vl2tab[4], *vl2e=NULL, *vl2_table = NULL; + unsigned long l1tab; + unsigned long ppt_alloc = 0; + unsigned long count; + int i = 0; +#if _LEVEL_3_ + l3_pgentry_t *vl3tab = NULL; + unsigned long l2tab; + if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + toptab >> PAGE_SHIFT)) == NULL ) + goto error_out; + for (i = 0; i < 4 ; i++) { + l2tab = vl3tab[i] & PAGE_MASK; + vl2tab[i] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l2tab >> PAGE_SHIFT); + if(vl2tab[i] == NULL) + goto error_out; + } + munmap(vl3tab, PAGE_SIZE); + vl3tab = NULL; +#else + if ( (vl2tab[0] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + toptab >> PAGE_SHIFT)) == NULL ) + goto error_out; +#endif + + for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ ) + { + if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) + { + vl2_table = vl2tab[get_vl2_table(count, v_start)]; + vl2e = &vl2_table[l2_table_offset( + v_start + (count << PAGE_SHIFT))]; + + l1tab = page_table_array[ppt_alloc++] << PAGE_SHIFT; + if ( vl1tab != NULL ) + munmap(vl1tab, PAGE_SIZE); + + if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l1tab >> PAGE_SHIFT)) == NULL ) + { + goto error_out; + } + memset(vl1tab, 0, PAGE_SIZE); + vl1e = &vl1tab[l1_table_offset(v_start + (count<> PAGE_SHIFT)) == NULL ) + goto error_out; + for (i = 0; i < 4 ; i ++){ + l2tab = vl3tab[i] & PAGE_MASK; + vl2tab[i] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l2tab >> PAGE_SHIFT); + if(vl2tab[i] == NULL) + goto error_out; + } + munmap(vl3tab, PAGE_SIZE); + vl3tab = NULL; +#else + if ( (vl2tab[0] = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + toptab >> PAGE_SHIFT)) == NULL ) + goto error_out; +#endif + + for ( count = 0; count < ((v_end-v_start)>>PAGE_SHIFT); count++ ){ + if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) + { + vl2_table = vl2tab[get_vl2_table(count, v_start)]; + vl2e = &vl2_table[l2_table_offset(v_start + (count << PAGE_SHIFT))]; + l1tab = *vl2e & PAGE_MASK; + + if(l1tab == 0) + continue; + if ( vl1tab != NULL ) + munmap(vl1tab, PAGE_SIZE); + + if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l1tab >> PAGE_SHIFT)) == NULL ) + { + goto error_out; + } + vl1e = &vl1tab[l1_table_offset(v_start + (count<ctrlreg[3] = l2tab; - /* Initialise the page tables. */ if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, l2tab >> PAGE_SHIFT)) == NULL ) @@ -415,23 +414,35 @@ static int setup_guest(int xc_handle, munmap(vl1tab, PAGE_SIZE); munmap(vl2tab, PAGE_SIZE); #else - /* here l3tab means pdpt, only 4 entry is used */ l3tab = page_array[ppt_alloc++] << PAGE_SHIFT; ctxt->ctrlreg[3] = l3tab; - /* Initialise the page tables. */ if ( (vl3tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, l3tab >> PAGE_SHIFT)) == NULL ) goto error_out; memset(vl3tab, 0, PAGE_SIZE); + /* Fill in every PDPT entry. */ + for ( i = 0; i < L3_PAGETABLE_ENTRIES_PAE; i++ ) + { + l2tab = page_array[ppt_alloc++] << PAGE_SHIFT; + if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, + PROT_READ|PROT_WRITE, + l2tab >> PAGE_SHIFT)) == NULL ) + goto error_out; + memset(vl2tab, 0, PAGE_SIZE); + munmap(vl2tab, PAGE_SIZE); + vl3tab[i] = l2tab | L3_PROT; + } + vl3e = &vl3tab[l3_table_offset(dsi.v_start)]; for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ ) { - if (!(count % (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){ - l2tab = page_array[ppt_alloc++] << PAGE_SHIFT; + if (!(count & (1 << (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)))){ + l2tab = vl3tab[count >> (L3_PAGETABLE_SHIFT - L1_PAGETABLE_SHIFT)] + & PAGE_MASK; if (vl2tab != NULL) munmap(vl2tab, PAGE_SIZE); @@ -441,8 +452,6 @@ static int setup_guest(int xc_handle, l2tab >> PAGE_SHIFT)) == NULL ) goto error_out; - memset(vl2tab, 0, PAGE_SIZE); - *vl3e++ = l2tab | L3_PROT; vl2e = &vl2tab[l2_table_offset(dsi.v_start + (count << PAGE_SHIFT))]; } if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 ) -- 2.30.2